﻿using AForge.Imaging;
using AForge.Imaging.Filters;
using ELTE.TFEG.Hough.EventHandling;
using ELTE.TFEG.ImageTransform.Hough;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace ELTE.TFEG.ImageTransform
{
    public class ImageProcess
    {
        public FilteringEvents eventHandling = new FilteringEvents();
        public HoughTransformEvents houghEventHandling = new HoughTransformEvents();

        Mean meanFilter = new Mean();
        Median medianFilter = new Median();

        ConservativeSmoothing conservativeSmoothingFilter = new ConservativeSmoothing();
        AdaptiveSmoothing adaptiveSmoothingFilter = new AdaptiveSmoothing();
        BilateralSmoothing bilateralSmoothingFilter = new BilateralSmoothing();

        HomogenityEdgeDetector homEdgeDetector = new HomogenityEdgeDetector();
        DifferenceEdgeDetector diffEdgeDetector = new DifferenceEdgeDetector();
        SobelEdgeDetector sobEdgeDetector = new SobelEdgeDetector();
        CannyEdgeDetector canEdgeDetector = new CannyEdgeDetector();

        HoughLineTransformation houghLineTransform = new HoughLineTransformation();

        List<Bitmap> imgs = new List<Bitmap>();

        public List<Bitmap> GetDenoisedImages(BitmapImage originalImage)
        {
            try
            {
                Bitmap bmp = new Bitmap(originalImage.UriSource.OriginalString);
                imgs.Add(meanFilter.Apply(bmp));
                imgs.Last().Tag = "Mean";
                imgs.Add(medianFilter.Apply(bmp));
                imgs.Last().Tag = "Median";
                imgs.Add(conservativeSmoothingFilter.Apply(bmp));
                imgs.Last().Tag = "Conservative";
                imgs.Add(adaptiveSmoothingFilter.Apply(bmp));
                imgs.Last().Tag = "Adaptive";
                imgs.Add(bilateralSmoothingFilter.Apply(bmp));
                imgs.Last().Tag = "Bilateral";
            }
            catch (Exception ex)
            {

            }
            return imgs;
        }

        public List<Bitmap> GetEdgeDetectedImages(BitmapImage originalImage)
        {

            try
            {

                Bitmap bmp = Grayscale.CommonAlgorithms.Y.Apply(originalImage.GetBitmap());
                bmp.Save(originalImage.UriSource.OriginalString.AddSuffixToFilePath(Constants.grayScaleSuffix));
                List<Bitmap> edgeDetectedImages = GetEdgeDetectedImages(bmp);
                edgeDetectedImages.ForEach(img =>
                    {
                        string fileName = String.Empty;
                        //save the image to disk
                        switch (img.Tag.ToString())
                        {
                            case Constants.homFilterSuffix:
                                fileName = originalImage.UriSource.OriginalString.AddSuffixToFilePath(Constants.homFilterSuffix);
                                break;
                            case Constants.sobFilterSuffix:
                                fileName = originalImage.UriSource.OriginalString.AddSuffixToFilePath(Constants.sobFilterSuffix);
                                break;
                            case Constants.canFilterSuffix:
                                fileName = originalImage.UriSource.OriginalString.AddSuffixToFilePath(Constants.canFilterSuffix);
                                break;
                            case Constants.diffFilterSuffix:
                                fileName = originalImage.UriSource.OriginalString.AddSuffixToFilePath(Constants.diffFilterSuffix);
                                break;
                            default:
                                break;
                        }
                        if (!String.IsNullOrEmpty(fileName))
                        {
                            img.Save(fileName);
                        }
                    });
                return edgeDetectedImages;

            }
            catch (Exception ex)
            {

            }
            return new List<Bitmap>();
        }

        public Bitmap GetGrayScaledImage(Bitmap originalImage)
        {
            return Grayscale.CommonAlgorithms.Y.Apply(originalImage);
        }

        public List<Bitmap> GetEdgeDetectedImages(Bitmap grayScaledImage)
        {
            List<Bitmap> edgeDetectedImages = new List<Bitmap>();
            try
            {
                //apply the homogenity edge detection
                edgeDetectedImages.Add(homEdgeDetector.Apply(grayScaledImage));
                edgeDetectedImages.Last().Tag = Constants.homFilterSuffix;
                //EAP ->
                //eventHandling.OnFilterApplied(new FilterAppliedEventArgs(Constants.homFilterName));
                //apply the difference edge detection
                edgeDetectedImages.Add(diffEdgeDetector.Apply(grayScaledImage));
                edgeDetectedImages.Last().Tag = Constants.diffFilterSuffix;
                //EAP ->
                //eventHandling.OnFilterApplied(new FilterAppliedEventArgs(Constants.diffFilterName));
                //apply the sobel edge detection 
                edgeDetectedImages.Add(sobEdgeDetector.Apply(grayScaledImage));
                edgeDetectedImages.Last().Tag = Constants.sobFilterSuffix;
                //EAP ->
                //eventHandling.OnFilterApplied(new FilterAppliedEventArgs(Constants.sobFilterName));
                //apply the canny edge detection
                edgeDetectedImages.Add(canEdgeDetector.Apply(grayScaledImage));
                edgeDetectedImages.Last().Tag = Constants.canFilterSuffix;
                //EAF ->
                //eventHandling.OnFilterApplied(new FilterAppliedEventArgs(Constants.canFilterName));
            }
            catch (Exception ex)
            {

            }
            return edgeDetectedImages;
        }

        /// <summary>
        /// Gets the hough detected image
        /// </summary>
        /// <param name="edgeDetectedImage"></param>
        /// <returns></returns>
        public Bitmap GetHoughLine(BitmapImage edgeDetectedImage, int percentage)
        {
            try
            {
                if (edgeDetectedImage != null)
                {
                    Bitmap bmp = edgeDetectedImage.GetBitmap();
                    HoughTransform houghTransform = new HoughTransform();
                    //houghLineTransform.ProcessImage(bmp);
                    Bitmap houghMap = houghTransform.Line_GetHoughMap(bmp);
                    //houghMap.Save(@"D:\Docs\Docs - ELTE\TAN - TFEG\Sample images2\houghmap.png");
                    houghMap.Dispose();
                    double dPercentage = (double)percentage/100;
                    return houghTransform.GetOriginalImageWithLinesFound(bmp, dPercentage);

                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public Bitmap GetHoughLineSegments(BitmapImage edgeDetectedImage, int percentage)
        {
            try
            {
                if (edgeDetectedImage != null)
                {
                    Bitmap bmp = edgeDetectedImage.GetBitmap();
                    HoughTransform houghTransform = new HoughTransform();
                    Bitmap houghMap = houghTransform.Line_GetHoughMap(bmp);
                    //houghMap.Save(@"D:\Docs\Docs - ELTE\TAN - TFEG\Sample images2\houghmap.png");
                    houghMap.Dispose();
                    double dPercentage = (double)percentage / 100;
                    return houghTransform.GetOriginalImageWithLineSegmentsFound(bmp, dPercentage);

                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        public Bitmap GetHoughCircle(BitmapImage edgeDetectedImage, int percentage, int circleRadius, bool shouldDistinct, bool shouldTraceDown)
        {
            try
            {
                if (edgeDetectedImage != null)
                {
                    Bitmap bmp = edgeDetectedImage.GetBitmap();
                    HoughTransform houghTransform = new HoughTransform();
                    double dPercentage = (double)percentage / 100;
                    return houghTransform.GetOriginalImageWithCirclesFound(bmp, dPercentage, circleRadius, shouldDistinct, shouldTraceDown);
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        void Events_TransformEvent(object sender, HoughTransformEventargs args)
        {
            houghEventHandling.OnTransformEvent(args);
        }


    }
}
